home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Ebooks / Thinking in C++ V2 / C25 / VirtualConstructor.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  2.6 KB  |  106 lines

  1. //: C25:VirtualConstructor.cpp
  2. // From Thinking in C++, 2nd Edition
  3. // Available at http://www.BruceEckel.com
  4. // (c) Bruce Eckel 1999
  5. // Copyright notice in Copyright.txt
  6. #include <iostream>
  7. #include <string>
  8. #include <exception>
  9. #include <vector>
  10. using namespace std;
  11.  
  12. class Shape {
  13.   Shape* s;
  14.   // Prevent copy-construction & operator=
  15.   Shape(Shape&);
  16.   Shape operator=(Shape&);
  17. protected:
  18.   Shape() { s = 0; };
  19. public:
  20.   virtual void draw() { s->draw(); }
  21.   virtual void erase() { s->erase(); }
  22.   virtual void test() { s->test(); };
  23.   virtual ~Shape() {
  24.     cout << "~Shape\n";
  25.     if(s) {
  26.       cout << "Making virtual call: ";
  27.       s->erase(); // Virtual call
  28.     }
  29.     cout << "delete s: ";
  30.     delete s; // The polymorphic deletion
  31.   }
  32.   class BadShapeCreation : public exception {
  33.     string reason;
  34.   public:
  35.     BadShapeCreation(string type) {
  36.       reason = "Cannot create type " + type;
  37.     }
  38.     const char *what() const { 
  39.       return reason.c_str(); 
  40.     }
  41.   };
  42.   Shape(string type) throw(BadShapeCreation);
  43. };
  44.  
  45. class Circle : public Shape {
  46.   Circle(Circle&);
  47.   Circle operator=(Circle&);
  48.   Circle() {} // Private constructor
  49.   friend class Shape;
  50. public:
  51.   void draw() { cout << "Circle::draw\n"; }
  52.   void erase() { cout << "Circle::erase\n"; }
  53.   void test() { draw(); }
  54.   ~Circle() { cout << "Circle::~Circle\n"; }
  55. };
  56.  
  57. class Square : public Shape {
  58.   Square(Square&);
  59.   Square operator=(Square&);
  60.   Square() {}
  61.   friend class Shape;
  62. public:
  63.   void draw() { cout << "Square::draw\n"; }
  64.   void erase() { cout << "Square::erase\n"; }
  65.   void test() { draw(); }
  66.   ~Square() { cout << "Square::~Square\n"; }
  67. };
  68.  
  69. Shape::Shape(string type) 
  70.   throw(Shape::BadShapeCreation) {
  71.   if(type == "Circle") 
  72.     s = new Circle();
  73.   else if(type == "Square")
  74.     s = new Square();
  75.   else throw BadShapeCreation(type);
  76.   draw();  // Virtual call in the constructor
  77. }
  78.  
  79. char* shlist[] = { "Circle", "Square", "Square",
  80.   "Circle", "Circle", "Circle", "Square", "" };
  81.  
  82. int main() {
  83.   vector<Shape*> shapes;
  84.   cout << "virtual constructor calls:" << endl;
  85.   try {
  86.     for(char** cp = shlist; **cp; cp++)
  87.       shapes.push_back(new Shape(*cp));
  88.   } catch(Shape::BadShapeCreation e) {
  89.     cout << e.what() << endl;
  90.     return 1;
  91.   }
  92.   for(int i = 0; i < shapes.size(); i++) {
  93.     shapes[i]->draw();
  94.     cout << "test\n";
  95.     shapes[i]->test();
  96.     cout << "end test\n";
  97.     shapes[i]->erase();
  98.   }
  99.   Shape c("Circle"); // Create on the stack
  100.   cout << "destructor calls:" << endl;
  101.   for(int j = 0; j < shapes.size(); j++) {
  102.     delete shapes[j];
  103.     cout << "\n------------\n";
  104.   }
  105. } ///:~
  106.